#ifndef _C_GL_DEVICE_H_
#define _C_GL_DEVICE_H_

//////////////////////////////////////////////////////////////////////////
/// C_gl_Device is a child of I_api_Device
//////////////////////////////////////////////////////////////////////////
#include "../interface/I_api_Device.h"
//#include "../interface/I_api_VertexShader.h"
//#include "../interface/I_api_PixelShader.h"
//#include "../interface/I_api_Program.h"
#include "../interface/I_api_SamplerState.h"
#include "../interface/I_api_RasterizerState.h"
#include "../interface/I_api_DepthStencilState.h"

//////////////////////////////////////////////////////////////////////////
/// Gl interfaces includes
//////////////////////////////////////////////////////////////////////////
#include "../interface/C_gl_Buffer.h"
#include "../interface/C_gl_Texture_2D.h"
#include "../interface/C_gl_VertexShader.h"
#include "../interface/C_gl_PixelShader.h"
#include "../interface/C_gl_Program.h"
#include "../interface/C_gl_FrameBuffer.h"

class C_gl_Device : public I_api_Device
{
protected:
	int m_DeviceId;

	virtual	u32	ComparisonToOpenGL(E_api_Comparison_Func func) const;
	virtual	u32	StencilopToOpenGL(E_api_Stencil_Op op) const;
	virtual	u32	FormatToOpenGLInternal(E_api_Format format) const;
	virtual	u32	FormatToOpenGLFormat(E_api_Format format) const;
	virtual	u32	FormatToOpenGLType(E_api_Format format) const;

public:
	C_gl_Device()
	{ 
		m_DeviceId = 0; 

		glEnable(GL_DEPTH_TEST);		
		glEnable(GL_TEXTURE_1D);
		glEnable(GL_TEXTURE_1D_ARRAY_EXT);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_TEXTURE_2D_ARRAY_EXT);
		glEnable(GL_TEXTURE_3D);
		glEnable(GL_CULL_FACE);
	}
	C_gl_Device(void *pDevice) 
	{ 
		m_DeviceId = *((int*)pDevice);

		glEnable(GL_DEPTH_TEST);		
		glEnable(GL_TEXTURE_1D);
		glEnable(GL_TEXTURE_1D_ARRAY_EXT);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_TEXTURE_2D_ARRAY_EXT);
		glEnable(GL_TEXTURE_3D);
		glEnable(GL_CULL_FACE);
	}
	virtual ~C_gl_Device(){ m_DeviceId = 0; }

	virtual void		Set(void *pDevice) { m_DeviceId = *((int*)pDevice); }
	virtual void	*	Get(void) { return &m_DeviceId; }

	//////////////////////////////////////////////////////////////////////////
	/// Create calls
	//////////////////////////////////////////////////////////////////////////
	virtual bool		CreateBuffer(const S_api_BufferDesc *pDesc, const S_api_Subresource_Data *pInitialData, I_api_Buffer ** ppBuffer);
	virtual	bool		CreateTexture2D(const S_api_Texture2D_Desc *pDesc, const S_api_Subresource_Data *pInitialData, I_api_Texture_2D **ppTexture2D);

	virtual	bool		CreateShaderResourceView(I_api_Resource * pResource, const S_api_ShaderResourceView_Desc *pDesc, I_api_ShaderResourceView **ppSRView);
	virtual	bool		CreateRenderTargetView(I_api_Resource	* pResource, const S_api_RenderTargetView_Desc *pDesc, I_api_RenderTargetView **ppRTView);
	virtual	bool		CreateDepthStencilView(I_api_Resource * pResource, const S_api_DepthStencilView_Desc *pDesc, I_api_DepthStencilView **ppDepthStencilView);
	virtual	bool		CreateUnorderedAccessView(I_api_Resource * pResource, const S_api_UnorderedAccessView_Desc *pDesc, I_api_UnorderedAccessView **ppUnordererdAccessView);
	virtual	bool		CreateFramebuffer(int nRenderTargetView, I_api_RenderTargetView ** pRenderTargetView, I_api_DepthStencilView * pDepthStencilView, I_api_Framebuffer ** ppFramebuffer);

	virtual bool		CreateVertexShader(const void *pShaderBytecode, int BytecodeLength, I_api_VertexShader **ppVertexShader);
	virtual bool		CreatePixelShader(const void *pShaderBytecode, int BytecodeLength, I_api_PixelShader **ppPixelShader);
	virtual bool		CreateProgram(I_api_VertexShader *pVertexShader, I_api_PixelShader *pPixelShader, I_api_Program ** ppProgram, I_api_Blob ** ppErrorMsg);
	
	virtual	bool		CreateRasterizerState(const S_api_Rasterizer_Desc * pDesc, I_api_RasterizerState **ppRasterizerState);
	virtual	bool		CreateDepthStencilState(const S_api_DepthStencilState * pDesc, I_api_DepthStencilState **ppDepthStencilState);

	//////////////////////////////////////////////////////////////////////////
	/// Draw calls
	//////////////////////////////////////////////////////////////////////////
	virtual void		DrawIndexed(int IndexCount, int StartIndexLocation, int BaseVertexLocation);
	virtual void		Draw(int VertexCount, int StartVertexLocation);

	virtual void		Flush();

	//////////////////////////////////////////////////////////////////////////
	/// IA calls
	//////////////////////////////////////////////////////////////////////////
	virtual void		IAGetInputLayout(I_api_InputLayout **ppInputLayout) { *ppInputLayout = m_pCurrentInputLayout; }
	virtual void		IASetInputLayout(I_api_InputLayout *pInputLayout) { m_pCurrentInputLayout = pInputLayout; }
	virtual void		IASetVertexBuffers(int StartSlot, int NumBuffers, I_api_Buffer **ppVertexBuffers, int *pStrides, int *pOffsets);

	virtual void		VSSetShader(I_api_VertexShader *){};
	//virtual void GSSetShader(I_api_GeometryShader *){};
	virtual void		PSSetShader(I_api_PixelShader *){};

	virtual void		SetProgram(I_api_Program *pProgram);

	virtual	void		RSSetState(I_api_RasterizerState *pRasterizerState);

	//////////////////////////////////////////////////////////////////////////
	/// OM calls
	//////////////////////////////////////////////////////////////////////////
	virtual	void		OMSetRenderTargets(int NumViews, I_api_RenderTargetView *const *ppRenderTargetViews, I_api_DepthStencilView **ppDepthStencilView){};
	virtual	void		OMGetRenderTargets(int NumViews, I_api_RenderTargetView			 **ppRenderTargetViews, I_api_DepthStencilView **ppDepthStencilView){};
	virtual	void		OMSetFramebuffer(I_api_Framebuffer	*pFramebuffer);
	virtual	void		OMSetDepthStencilState(I_api_DepthStencilState *pDepthStencilState, u32 StencilRef);

	//////////////////////////////////////////////////////////////////////////
	/// Clear calls
	//////////////////////////////////////////////////////////////////////////
	virtual	void		ClearRenderTargetView(I_api_RenderTargetView *pRenderTargetView, const float ColorRGBA[4]);
	virtual	void		ClearDepthStencilView(I_api_DepthStencilView *pDepthStencilView, u32 ClearFlags, float Depth, u8 Stencil);
	virtual	void		ClearFramebuffer(I_api_Framebuffer *pFramebuffer, u32 ClearMask, const float Color[4], float Depth, u8 Stencil);
};

#endif